package edu.temple.templepatco;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;

/**
 * This class represents a single possible path from Cecil B. Moore to Camden
 */
public class Route implements Comparable<Route> {

	private Stop[] stops;
	private String label;
	private Date requestTime;

	// prevent creation of empty routes
	@SuppressWarnings("unused")
	/**
	 * Placeholder private constructor to prevent creation of empty Route objects. Never use this constructor
	 */
	private Route() {
		stops = null;
	}

	/**
	 * Constructs a Route from the given list of times
	 * 
	 * @param times
	 *            The time of every stop along the Route in order
	 * @param reqTime
	 *            The time that the Route was requested
	 */
	public Route(Date[] times, Date reqTime) {
		stops = new Stop[times.length];
		for (int i = 0; i < times.length; i++) {
			stops[i] = new Stop("unknown", times[i]);
		}
		requestTime = (Date) reqTime.clone();
	}

	/**
	 * Constructs a Route from the given list of Stop
	 * 
	 * @param theStops
	 *            Every Stop along the Route should appear in order in this list
	 * @param reqTime
	 *            The time that the Route was requested
	 */
	public Route(Stop[] theStops, Date reqTime) {
		if (theStops != null) {
			this.stops = new Stop[theStops.length];
			System.arraycopy(theStops, 0, this.stops, 0, theStops.length);
		}
		requestTime = (Date) reqTime.clone();
	}

	/**
	 * Constructs a Route from the given list of Stop
	 * 
	 * @param theStops
	 *            Every Stop along the Route should appear in order in this list
	 * @param l
	 *            A text label for the Route that will is used by the UI
	 * @param reqTime
	 *            The time that the Route was requested
	 */
	public Route(Stop[] theStops, String l, Date reqTime) {
		if (theStops != null) {
			this.stops = new Stop[theStops.length];
			System.arraycopy(theStops, 0, this.stops, 0, theStops.length);
		}
		label = l;
		requestTime = (Date) reqTime.clone();
	}

	/**
	 * Compares this Route to another Route based on earliest final arrival time
	 * and in the case of a tie compares based on latest departure time
	 * 
	 * @param another
	 *            The Route to compare to
	 * @return -1 if this Route is better, 1 if another is better, and 0 if they
	 *         are the same
	 */
	public int compareTo(Route another) {
		int firstCmp = this.getEndTime().compareTo(another.getEndTime());
		if (firstCmp == 0) {
			// if both routes arrive in NJ at the same time sort by which route
			// starts LATER
			return -1 * this.getStops()[0].getTime().compareTo(another.getStops()[0].getTime());
		} else {
			return firstCmp;
		}
	}

	/**
	 * Gives the time of arrival at the final stop in the Route
	 * 
	 * @return time of arrival at the final stop in the Route
	 */
	public Date getEndTime() {
		if (stops != null && stops.length > 0)
			return stops[stops.length - 1].getTime();
		else
			return null;
	}

	/**
	 * Gives a String containing the label of the Route combined with the time
	 * of the final stop
	 * 
	 * @return The label and final time in String form
	 */
	public String getLabel() {
		SimpleDateFormat df = new SimpleDateFormat(": h:mm a");
		return label + df.format(getEndTime());
	}

	/**
	 * Returns the time for which the Route was calculated
	 * 
	 * @return the time for which the Route was calculated
	 */
	public Date getRequestTime() {
		return (Date) requestTime.clone();
	}

	/**
	 * Returns the list of stops used by the Route in order
	 * 
	 * @return the list of stops used by the Route in order
	 */
	public Stop[] getStops() {
		return Arrays.copyOf(stops, stops.length);
	}

	@Override
	/**
	 * Converts the entire route into one long string formed by concatenating all the stops together
	 * @return A String that contains every stop
	 */
	public String toString() {
		StringBuilder sb = new StringBuilder();
		if (stops != null) {
			for (Stop s : stops) {
				if (sb.length() > 0) {
					sb.append(" -> ");
				}
				sb.append(s.getName()).append(":  ").append(s.getTime().toString());
			}
			return sb.toString();
		} else {
			return null;
		}

	}
}
